package com.lovely3x.jobservice;

import android.app.Notification;
import android.app.Service;
import android.content.Intent;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.Parcelable;
import android.support.annotation.MainThread;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.support.annotation.WorkerThread;
import android.text.TextUtils;

import com.lovely3x.common.requests.Config;
import com.lovely3x.common.utils.ALog;
import com.lovely3x.jobservice.executors.TaskExecutor;
import com.lovely3x.jobservice.executors.extensions.downloader2.factory.DownloaderFactory;
import com.lovely3x.jobservice.executors.extensions.version.factory.VersionCheckFactory;
import com.lovely3x.jobservice.factory.ExecutorFactory;
import com.lovely3x.jobservice.task.Progress;
import com.lovely3x.jobservice.task.Task;
import com.lovely3x.jobservice.utils.ArrayMap;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 工作服务
 * Created by lovely3x on 16-1-26.
 */
public class JobService extends Service {

    public static final String TAG = "JobService";

    /**
     * 是否开启DEBUG
     */
    public static final boolean DEBUG = Config.DEBUG;

    /**
     * 数据库名
     */
    public static final String DB_NAME = "db_task_list";

    /**
     * 传递动作的key
     */
    public static final String EXTRA_ACTION = "job.service.action";

    /**
     * 添加任务的动作
     */
    public static final int ACTION_ADD_TASK = 0x1;
    /**
     * 取消任务
     */
    public static final int ACTION_CANCEL_TASK = ~0x0;
    /**
     * 暂停任务的动作
     */
    public static final int ACTION_PAUSE_TASK = ~0x1;
    /**
     * 添加任务执行者
     * 需要通过{@link #EXTRA_EXECUTOR_NAME} 传递一个String 表示一个类的全限定名
     * 这个类会被添加到执行者列表中
     */
    public static final int ACTION_ADD_FACTORY = ~0x2;
    /**
     * 暂停所有的任务
     */
    public static final int ACTION_PAUSE_ALL_TASK = ~0x3;
    /**
     * 获取所有的任务列表
     */
    public static final int ACTION_GET_TASKS = ~0x4;
    /**
     * 恢复指定的暂停的任务
     */
    public static final int ACTION_RESUME_TASK = ~0x5;
    /**
     * 回复所有暂停的任务
     */
    public static final int ACTION_RESUME_ALL_TASK = ~0x6;
    /**
     * 自动更新进度
     */
    public static final int ACTION_AUTOMATIC_UPDATE_PROGRESS = ~0x7;
    /**
     * 发布一次进度
     */
    public static final int ACTION_UPDATE_PROGRESS_ONCE = ~0x8;

    /**
     * 停止服务
     */
    public static final int ACTION_STOP_SERVICE = ~0x9;

    /**
     * 创建服务，不管服务之前是否创建都会回调创建成功
     */
    public static final int ACTION_CREATE_SERVICE_IF_NEED = ~0x10;

    /**
     * 将服务绑定到前台
     * 需要一个通知对象{@link #EXTRA_NOTIFICATION}
     */
    public static final int ACTION_START_FOREGROUND = ~0x11;

    /**
     * 取消前台服务
     * 可以通过 {@link #EXTRA_REMOVE_NOTIFICATION}携带一个 boolean值表示是否移除通知
     */
    public static final int ACTION_STOP_FOREGROUND = ~0x12;


    /**
     * 携带执行者名字的key
     */
    public static final String EXTRA_EXECUTOR_NAME = "job.service.extra.add.executor.name";
    /**
     * 传递任务列表的key
     */
    public static final String EXTRA_TASK_LIST = "job.service.extra.task.list";
    /**
     * 广播任务的进度同时需要传递一个{@link #EXTRA_PROGRESS}
     */
    public static final String BROAD_ACTION_PROGRESS = "job.service.broad.action.progress";
    /**
     * 广播任务进度时携带的任务进度对象
     * 任务进度为 一个{@link Bundle} bundle中存放了数据集合
     */
    public static final String EXTRA_PROGRESS = "job.service.progress";
    /**
     * 传递任务对象的key
     */
    public static final String EXTRA_TASK = "job.service.task";
    /**
     * 传递任务的标识的key
     */
    public static final String EXTRA_TASK_WHAT = "job.service.task.what";


    /**
     * 工厂名
     */
    public static final String EXTRA_FACTORY_CLASS_NAME = "job.service.factory.clazz.name";

    /**
     * 任务的执行结果
     */
    public static final String EXTRA_TASK_EXECUTED_RESULT = "job.service.task.executed.result";
    /**
     * 是否开启自动更新进度
     */
    public static final String EXTRA_AUTOMATIC_UPDATE_PROGRESS = "job.service.task.automatic.update.progress";
    /**
     * 自动更新的更新间隔，在没有打开自动更新时这个值无效
     */
    public static final String EXTRA_AUTOMATIC_UPDATE_PROGRESS_INTERVAL = "job.service.task.automatic.progress.interval";
    /**
     * 传递任务的移除结果
     */
    public static final String EXTRA_TASK_REMOVE_RESULT = "job.service.task.remove.result";
    /**
     * 任务暂停结果
     */
    public static final String EXTRA_TASK_PAUSE_RESULT = "job.service.task.stop.result";
    /**
     * 传递恢复任务的结果
     */
    public static final String EXTRA_RESUME_TASK_RESULT = "job.service.task.resume.result";
    /**
     * 异常对象
     * 在任务执行失败时可以携带
     * #其他的失败情况还没加入
     */
    public static final String EXTRA_EXCEPTION = "job.service.broad.extra.exception";

    /**
     * 在将服务绑定到前台时，传递的通知对象
     */
    public static final String EXTRA_NOTIFICATION = "job.service.broad.extra.notification";

    /***
     * 在服务绑定到前台时，传递的notify id
     */
    public static final String EXTRA_NOTIFY_ID = "job.service.broad.extra.notify.id";


    /**
     * 停止服务时传递的参数，是否移除通知
     */
    public static final String EXTRA_REMOVE_NOTIFICATION = "job.service.broad.extra.remove.notification";


    /**
     * 广播任务的结果,同时需要传递
     * 任务的标识{@link #EXTRA_TASK_WHAT}
     * 和任务的执行结果{@link #EXTRA_TASK_EXECUTED_RESULT}
     */
    public static final String BROAD_ACTION_TASK_EXECUTED = "job.service.broad.action.task.executed";
    /**
     * 发布一个任务列表进度
     */
    public static final String BROAD_ACTION_TASK_LIST = "job.service.broad.action.task.list";

    /**
     * 发布一个任务移除结果广播
     * 这个广播发出时同样会携带一个 {@link #EXTRA_TASK}
     * 和一个任务移除结果{@link #EXTRA_TASK_REMOVE_RESULT}
     */
    public static final String BROAD_ACTION_REMOVE_RESULT = "job.service.broad.action.remove.task.result";


    /**
     * 服务销毁了
     */
    public static final String BROAD_ACTION_SERVICE_DESTROYED = "job.service.broad.action.service.destroyed";

    /**
     * 服务启动了
     */
    public static final String BROAD_ACTION_SERVICE_CREATED = "job.service.broad.action.service.created";

    /**
     * 服务初始化完成了
     */
    public static final String BROAD_ACTION_SERVICE_INITIALIZED = "job.service.broad.action.service.initialized";
    /**
     * 暂停任务的结果
     */
    public static final String BROAD_ACTION_PAUSE_TASK_RESULT = "job.service.broad.action.stop.task.result";
    /**
     * 广播任务开始
     */
    public static final String BROAD_ACTION_STARTED_TASK_RESULT = "job.service.broad.action.started.task.result";


    /**
     * 默认的自动更新进度更新间隔
     */
    public static final long DEFAULT_AUTOMATIC_UPDATE_PROGRESS_INTERVAL = 2 * 1000;

    /**
     * 默认的状态扫描间隔
     */
    public static final long DEFAULT_STATE_SCAN_INTERVAL = 1 * 1000;
    /**
     * 默认的服务状态空闲退出延迟
     */
    public static final long DEFAULT_SERVICE_EXIT_DELAY = 3 * 60 * 1000;
    /**
     * 默认的序列化间隔
     */
    public static final int DEFAULT_SERIALIZE_INTERVAL = 5 * 1000;


    /**
     * 恢复任务的结果
     */
    public static final String BROAD_ACTION_RESUME_RESULT = "job.service.broad.action.resume.task.result";
    /**
     * 等待队列中的操作类型,执行任务
     */
    public static final int TYPE_EXEC = 1;
    /**
     * 等待队列中的操作类型,恢复任务
     */
    public static final int TYPE_RESUME = 2;

    /**
     * 默认的通知提升到前台的id
     */
    public static final int DEFAULT_NOTIFY_ID = 0x1000234;


    /**
     * 任务等待队列
     */
    protected final ArrayMap<Task, Integer> TASK_QUEUE = new ArrayMap<>();


    /**
     * 主线程的handler
     * 有关主线程的操作都被提交到这里
     */
    protected final Handler UI_HANDLER = new Handler(Looper.getMainLooper());

    /**
     * 任务执行者工厂,用于生产任务执行者
     */
    protected final ArrayList<ExecutorFactory> EXECUTOR_FACTORIES = new ArrayList<>();

    /**
     * 任务表
     */
    protected final ArrayList<ExecWrapper> EXEC_TASK = new ArrayList<>();


    /**
     * 任务执行者线程池
     * 所有的执行者都是运行在这个线程池里的
     */
    protected ExecutorService TASK_EXECUTORS_POOL;
    /**
     * 单工作线程，用来在工作线程中执行一些耗时操作
     */
    protected ExecutorService TASK_SINGLE_THREAD;

    /**
     * 自动发布进度
     */
    protected boolean mAutomaticUpdateProgress = false;
    /**
     * 自动发布进度的间隔
     */
    protected long mAutomaticUpdateProgressInterval = DEFAULT_AUTOMATIC_UPDATE_PROGRESS_INTERVAL;
    /**
     * 是否已经销毁
     */
    protected boolean isDestroyed;
    /**
     * 自动进度提交可执行代码
     */
    protected Runnable mAutoProgressRunnable;
    /**
     * 任务执行器状态扫描器
     */
    protected ExecutorsStateMonitor mExecutorsScanner;
    /**
     * 执行器状态扫描间隔
     */
    protected long stateScanInterval = DEFAULT_STATE_SCAN_INTERVAL;
    /**
     * 服务空闲退出时间
     */
    protected long serviceExitDelay = DEFAULT_SERVICE_EXIT_DELAY;
    /**
     * 序列化间隔
     */
    protected int serialInterval = DEFAULT_SERIALIZE_INTERVAL;
    /**
     * 关闭服务的代码
     */
    protected Runnable selfKiller = new Runnable() {
        @Override
        public void run() {
            stopSelf();
        }
    };

    /**
     * 序列化监视器
     */
    private SerialMonitor mSerialMonitor;

    /**
     * 服务是否初始化完成
     */
    private boolean mServiceInitialized;

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        TASK_EXECUTORS_POOL = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 4);
        TASK_SINGLE_THREAD = Executors.newSingleThreadExecutor();

        //如果启动后,退出代码还没执行就移除执行退出的代码
        UI_HANDLER.removeCallbacks(selfKiller);
        isDestroyed = false;
        //广播服务被创建
        broadcastOnServiceCreated();
        //创建工厂
        makeExecutorFactories();
        //回调工厂被创建了
        callBackOnCreate();

        //启动状态监视进程
        mExecutorsScanner = new ExecutorsStateMonitor(JobService.this, stateScanInterval, serviceExitDelay);
        mExecutorsScanner.start();

        //启动序列化监视器
        mSerialMonitor = new SerialMonitor(this, serialInterval);
        mSerialMonitor.start();

        //恢复任务列表
        restoreTaskListFromSerializer();
    }

    /**
     * 执行onCreate回调给执行者工厂
     */
    @MainThread
    protected void callBackOnCreate() {
        for (ExecutorFactory ef : EXECUTOR_FACTORIES) ef.onCreate(this);
    }


    /**
     * 执行onDestroy 回调给执行者工厂
     */
    @MainThread
    protected void callBackOnDestroy() {
        for (ExecutorFactory ef : EXECUTOR_FACTORIES) ef.onDestroy(this);
    }


    /**
     * 发送服务初始化完成广播
     */
    protected void broadcastServiceInitialized() {
        this.mServiceInitialized = true;
        sendBroadcast(new Intent(BROAD_ACTION_SERVICE_INITIALIZED));
    }

    /**
     * 广播服务创建成功
     */
    protected void broadcastOnServiceCreated() {
        sendBroadcast(new Intent(BROAD_ACTION_SERVICE_CREATED));
    }

    /**
     * 广播服务销毁
     */
    protected void broadcastOnServiceDestroyed() {
        sendBroadcast(new Intent(BROAD_ACTION_SERVICE_DESTROYED));
    }


    /**
     * 恢复任务记录
     */
    @WorkerThread
    protected void restoreTaskListFromSerializer() {
        TASK_SINGLE_THREAD.execute(new Runnable() {
            @Override
            public void run() {
                synchronized (EXECUTOR_FACTORIES) {
                    for (ExecutorFactory ef : EXECUTOR_FACTORIES) {
                        if (ef.getTaskSerializer() == null) continue;
                        List<? extends Task> tasks = ef.getTaskSerializer().deserializeTask();
                        List<? extends Progress> progresses = ef.getTaskSerializer().deserializeProgress();
                        if (tasks != null) {
                            if (progresses == null || progresses.isEmpty()) {
                                synchronized (EXEC_TASK) {
                                    for (Task task : tasks) {
                                        ExecWrapper taskWrapper = new ExecWrapper();
                                        taskWrapper.factory = ef;
                                        taskWrapper.task = task;
                                        taskWrapper.executor = ef.createExecutor(task);
                                        taskWrapper.progress = taskWrapper.executor.getProgress();
                                        EXEC_TASK.add(taskWrapper);
                                    }
                                }
                            } else {
                                synchronized (EXEC_TASK) {
                                    for (Task task : tasks) {
                                        ExecWrapper taskWrapper = new ExecWrapper();
                                        taskWrapper.factory = ef;
                                        taskWrapper.task = task;
                                        taskWrapper.executor = ef.createExecutor(task);
                                        for (Progress p : progresses) {
                                            if (p.getTask() == task.getWhat()) {
                                                Progress progress = taskWrapper.executor.getProgress();
                                                progress.setTask(p.getTask());
                                                progress.setState(p.getState());
                                                progress.setWhen(p.getWhen());
                                                progress.setMax(p.getMax());
                                                progress.setCurrent(p.getCurrent());
                                                taskWrapper.progress = progress;
                                                break;
                                            }
                                        }
                                        EXEC_TASK.add(taskWrapper);
                                    }
                                }
                            }
                        }
                    }
                    executeOnMainThread(new Runnable() {
                        @Override
                        public void run() {
                            //广播任务列表
                            broadcastTaskList();
                            //广播服务初始化完成
                            broadcastServiceInitialized();
                        }
                    });
                }
            }
        });
    }

    /**
     * 保存任务列表到序列化器中
     */
    @WorkerThread
    protected void saveTaskListToSerializer() {
        //// TODO: 16-2-3
    }

    /**
     * 创建任务执行者工厂
     */
    protected void makeExecutorFactories() {
        List<Class<? extends ExecutorFactory>> factories = getFactories();
        for (Class<? extends ExecutorFactory> factory : factories) {
            ExecutorFactory factoryObject = makeExecutorFactory(factory);
            if (factoryObject != null) EXECUTOR_FACTORIES.add(factoryObject);
        }
    }

    /**
     * 创建一个执行工厂
     *
     * @param factory 工厂类
     * @return null或创建的工厂对象
     */
    protected ExecutorFactory makeExecutorFactory(Class<? extends ExecutorFactory> factory) {
        ExecutorFactory executorFactory = null;
        try {
            executorFactory = factory.newInstance();
        } catch (Exception e) {
            if (DEBUG) {
                ALog.w(TAG, e);
            }
        }
        return executorFactory;
    }

    /**
     * 获取当前的所有工厂类
     *
     * @return 工厂类列表
     */
    protected List<Class<? extends ExecutorFactory>> getFactories() {
        List<Class<? extends ExecutorFactory>> factories = new ArrayList<>();
        factories.add(DownloaderFactory.class);
        factories.add(VersionCheckFactory.class);
        return factories;
    }

    /**
     * 官博暂停结果
     *
     * @param task 暂停的任务
     * @param e    暂停是否失败 如果异常为null则为执行成功否则这个对象就是失败原因
     */
    @MainThread
    protected void broadcastPauseResult(Task task, Exception e) {
        Intent intent = new Intent(BROAD_ACTION_PAUSE_TASK_RESULT);
        intent.putExtra(EXTRA_TASK_PAUSE_RESULT, e == null);
        intent.putExtra(EXTRA_EXCEPTION, e);
        intent.putExtra(EXTRA_TASK, task);
        sendBroadcast(intent);
    }

    /**
     * 执行任务
     *
     * @param executorWrapper 任务执行者
     * @param task            需要执行的任务
     */
    protected void performExecTask(@NonNull final ExecWrapper executorWrapper, @NonNull final Task task) {
        //在工作线程中执行
        TASK_EXECUTORS_POOL.execute(new Runnable() {
            @Override
            public void run() {
                final Exception execResult = executorWrapper.executor.execute(task);
                executorWrapper.executor.serialize(executorWrapper.factory.getTaskSerializer());
                executeOnMainThread(new Runnable() {
                    @Override
                    public void run() {
                        broadcastResult(executorWrapper, execResult == null, execResult);
                        poolTaskQueue();
                    }
                });
            }
        });
    }

    /**
     * 恢复指定的任务
     *
     * @param taskWhat 任务标识
     */
    @MainThread
    private void performResumeTask(final long taskWhat) {
        synchronized (EXEC_TASK) {
            for (final ExecWrapper executor : EXEC_TASK) {
                if (executor != null && executor.task != null && executor.task.getWhat() == taskWhat) {
                    //run on work thread
                    TASK_EXECUTORS_POOL.execute(new Runnable() {
                        @Override
                        public void run() {
                            final Exception resumeResult = executor.executor.resume(executor.task, executor.progress);
                            executor.progress.setState(resumeResult == null ? Progress.State.SUCCESSFUL : Progress.State.FAILURE);
                            executeOnMainThread(new Runnable() {
                                @Override
                                public void run() {
                                    broadcastResumeResult(executor.task, resumeResult == null, resumeResult);
                                }
                            });
                        }
                    });
                    return;
                }
            }
        }
    }

    /**
     * 广播恢复结果
     *
     * @param task         需要恢复的的任务
     * @param isResumed    是否恢复成功
     * @param resumeResult 失败的原因，如果执行成功则为null
     */
    @MainThread
    protected void broadcastResumeResult(Task task, boolean isResumed, Exception resumeResult) {
        Intent intent = new Intent(BROAD_ACTION_RESUME_RESULT);
        intent.putExtra(EXTRA_RESUME_TASK_RESULT, isResumed);
        intent.putExtra(EXTRA_TASK, task);
        intent.putExtra(EXTRA_EXCEPTION, resumeResult);
        sendBroadcast(intent);
    }

    /**
     * 回复所有暂停的任务
     */
    private void performResumeAllTask() {
        //// TODO: 16-2-5
    }

    /**
     * 执行暂停所有的任务
     */
    private void performPauseAllTask() {
        //// TODO: 16-2-5
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        UI_HANDLER.removeCallbacks(selfKiller);
        if (intent != null) {
            onCommand(intent);
        }
        return super.onStartCommand(intent, flags, startId);
    }


    /**
     * 恢复暂停得到任务
     *
     * @param taskWhat 需要恢复的任务的标识
     */
    @MainThread
    protected void cmdResumeTask(long taskWhat) {
        performResumeTask(taskWhat);
    }


    /**
     * 接收到添加任务的指令
     *
     * @param task 需要添加的任务指令
     */
    @MainThread
    protected boolean cmdAddTask(Task task) {
        synchronized (EXECUTOR_FACTORIES) {
            for (ExecutorFactory ef : EXECUTOR_FACTORIES) {
                if (ef != null && ef.handleable(task)) {
                    if (!ef.isBusy()) {
                        TaskExecutor executor = ef.createExecutor(task);
                        if (executor != null) {
                            ExecWrapper exec = new ExecWrapper();
                            exec.progress = executor.getProgress();
                            exec.task = task;
                            exec.factory = ef;
                            exec.executor = executor;
                            exec.task.setCommitTime(System.currentTimeMillis());
                            synchronized (EXEC_TASK) {
                                EXEC_TASK.add(exec);
                            }
                            performExecTask(exec, task);
                            broadcastTaskStarted(task);
                            return true;
                        }
                    } else {//任务繁忙,加入任务队列中
                        TASK_QUEUE.put(task, TYPE_EXEC);
                        if (DEBUG)
                            ALog.d(TAG, String.format("任务执行器 %s 当前状态繁忙，任务 %s 被放入等待队列", ef, task.getWhat()));

                    }
                }
            }
        }
        return false;
    }

    /**
     * 广播任务被添加后执行
     */
    private void broadcastTaskStarted(Task task) {
        Intent intent = new Intent(BROAD_ACTION_STARTED_TASK_RESULT);
        intent.putExtra(EXTRA_TASK_WHAT, task.getWhat());
        sendBroadcast(intent);
    }


    /**
     * 当有启动命令执行后回调，每次调用{@link #startService(Intent)}都会调用
     *
     * @param intent 命令
     */
    private void onCommand(@NonNull Intent intent) {
        int action = intent.getIntExtra(EXTRA_ACTION, 0);
        if (DEBUG) ALog.i(TAG, "onCommand ->  " + action);
        switch (action) {
            case ACTION_ADD_TASK://添加任务
            {
                Parcelable parcelable = intent.getParcelableExtra(EXTRA_TASK);

                ALog.i(TAG, "Add task " + parcelable);

                if (parcelable instanceof Task) {
                    Task task = (Task) parcelable;
                    cmdAddTask(task);
                }
                break;
            }
            case ACTION_CANCEL_TASK://取消任务
            {
                long taskWhat = intent.getLongExtra(EXTRA_TASK_WHAT, -1);
                ALog.i(TAG, "Cancel task " + taskWhat);
                if (taskWhat != -1) {
                    cmdCancelTask(taskWhat);
                }
                break;
            }
            case ACTION_PAUSE_TASK://暂停任务
            {
                long taskWhat = intent.getLongExtra(EXTRA_TASK_WHAT, -1);

                if (taskWhat != -1) {
                    cmdPauseTask(taskWhat);
                }
                break;
            }
            case ACTION_ADD_FACTORY://添加任务工厂
            {
                //// TODO: 16-3-23
                String clazzName = intent.getStringExtra(EXTRA_FACTORY_CLASS_NAME);
                if (TextUtils.isEmpty(clazzName)) return;
                try {

                    synchronized (EXECUTOR_FACTORIES) {
                        for (ExecutorFactory factory : EXECUTOR_FACTORIES) {
                            if (factory != null && factory.getClass().getName().equals(clazzName)) {
                                //Already contained.
                                return;
                            }
                        }
                    }

                    Class<ExecutorFactory> factoryClass = (Class<ExecutorFactory>) Class.forName(clazzName);
                    ExecutorFactory executorFactory = makeExecutorFactory(factoryClass);
                    if (executorFactory != null) {
                        synchronized (EXECUTOR_FACTORIES) {
                            executorFactory.onCreate(this);
                            EXECUTOR_FACTORIES.add(executorFactory);
                        }
                    }
                } catch (Exception e) {
                    if (DEBUG) {
                        e.printStackTrace();
                    }
                }
                break;
            }
            case ACTION_PAUSE_ALL_TASK://暂停所有的任务
            {
                performPauseAllTask();
                break;
            }
            case ACTION_RESUME_TASK://恢复任务
            {
                long taskWhat = intent.getLongExtra(EXTRA_TASK_WHAT, -1);
                if (taskWhat != -1) {
                    cmdResumeTask(taskWhat);
                } else if (DEBUG) ALog.i(TAG, "无法恢复任务，因为这个任务的标志未指定");
                break;
            }
            case ACTION_RESUME_ALL_TASK://恢复所有的任务
            {
                performResumeAllTask();
                break;
            }
            case ACTION_AUTOMATIC_UPDATE_PROGRESS://自动更新任务
            {
                mAutomaticUpdateProgress = intent.getBooleanExtra(EXTRA_AUTOMATIC_UPDATE_PROGRESS, false);
                if (mAutomaticUpdateProgress)
                    mAutomaticUpdateProgressInterval = intent.getLongExtra(EXTRA_AUTOMATIC_UPDATE_PROGRESS_INTERVAL, mAutomaticUpdateProgressInterval);
                postProgress();
                break;
            }
            case ACTION_UPDATE_PROGRESS_ONCE://发布一次进度更新
            {
                postProgress();
                break;
            }
            case ACTION_GET_TASKS://获取任务列表
            {
                broadcastTaskList();
                break;
            }
            case ACTION_STOP_SERVICE://停止服务
            {
                stopSelf();
                break;
            }
            case ACTION_CREATE_SERVICE_IF_NEED: {//
                //如果服务已经初始化，那么立即回调初始化完成服务方法
                if (mServiceInitialized) broadcastServiceInitialized();
                break;
            }
            case ACTION_START_FOREGROUND://绑定到前台
                Notification notification = intent.getParcelableExtra(EXTRA_NOTIFICATION);
                int notifyId = intent.getIntExtra(EXTRA_NOTIFY_ID, DEFAULT_NOTIFY_ID);
                if (notification != null) {
                    startForeground(notifyId, notification);
                }
                break;
            case ACTION_STOP_FOREGROUND://从前台取消
                boolean removeNotification = intent.getBooleanExtra(EXTRA_REMOVE_NOTIFICATION, true);
                stopForeground(removeNotification);
                break;

        }
    }

    /**
     * 执行暂停任务
     *
     * @param taskWhat 需要暂停的任务
     */
    protected void cmdPauseTask(final long taskWhat) {
        if (DEBUG) ALog.i(TAG, String.format("任务 %d 执行暂停", taskWhat));
        TASK_SINGLE_THREAD.execute(new Runnable() {
            @Override
            public void run() {
                synchronized (EXEC_TASK) {
                    for (final ExecWrapper execWrapper : EXEC_TASK) {
                        if (execWrapper.task.getWhat() == taskWhat) {
                            final Exception pauseResult = execWrapper.executor.stop();
                            if (pauseResult == null) {
                                execWrapper.progress.setState(Progress.State.PAUSED);
                                execWrapper.executor.serialize(execWrapper.factory.getTaskSerializer());
                            }

                            executeOnMainThread(new Runnable() {
                                @Override
                                public void run() {
                                    broadcastPauseResult(execWrapper.task, pauseResult);
                                }
                            });
                            break;
                        }
                    }
                }
            }
        });
    }

    /**
     * 取消任务
     *
     * @param taskWhat 任务标识
     */
    protected void cmdCancelTask(final long taskWhat) {
        TASK_SINGLE_THREAD.execute(new Runnable() {
            @Override
            public void run() {
                synchronized (EXEC_TASK) {
                    final Iterator<ExecWrapper> it = EXEC_TASK.iterator();
                    while (it.hasNext()) {
                        final ExecWrapper next = it.next();
                        if (next.task.getWhat() == taskWhat) {
                            final boolean removeResult = next.executor.remove();
                            if (removeResult) {
                                it.remove();
                                if (next.factory.getTaskSerializer() != null) {
                                    next.factory.getTaskSerializer().deleteTask(next.task.getWhat());
                                    next.factory.getTaskSerializer().deleteProgress(next.task.getWhat());
                                }
                            }

                            executeOnMainThread(new Runnable() {
                                @Override
                                public void run() {
                                    broadRemoveResult(next.task, removeResult);
                                }
                            });
                            break;
                        }
                    }
                }
            }
        });
    }

    /**
     * 发送一条任务列表广播
     */
    @MainThread
    protected void broadcastTaskList() {
        Intent intent = new Intent(BROAD_ACTION_TASK_LIST);
        intent.putParcelableArrayListExtra(EXTRA_TASK_LIST, null);
        sendBroadcast(intent);
    }

    /**
     * 提交广播任务进度
     * 是否持续提交根据全局变量中的{@link #mAutomaticUpdateProgress} 值决定
     */
    protected void postProgress() {
        if (mAutoProgressRunnable != null) UI_HANDLER.removeCallbacks(mAutoProgressRunnable);
        UI_HANDLER.post(mAutoProgressRunnable = new Runnable() {
            @Override
            public void run() {
                broadcastProgress();
                if (mAutomaticUpdateProgress && !isDestroyed) {
                    UI_HANDLER.postDelayed(this, mAutomaticUpdateProgressInterval);
                }
            }
        });
    }

    /**
     * 获取主线程handler
     *
     * @return handler
     */
    public Handler getUIHandler() {
        return UI_HANDLER;
    }

    /**
     * 广播任务执行进度
     */
    @UiThread
    public void broadcastProgress() {
        //广播任务执行进度
        Intent intent = new Intent(BROAD_ACTION_PROGRESS);
        ArrayList<Task> taskList = new ArrayList<>();
        ArrayList<Progress> progressList = new ArrayList<>();
        synchronized (EXEC_TASK) {
            for (ExecWrapper wrapper : EXEC_TASK) {
                if (wrapper.task != null && wrapper.progress != null) {
                    taskList.add(wrapper.task);
                    progressList.add(wrapper.progress);
                }
            }
        }

        intent.putExtra(EXTRA_PROGRESS, progressList);
        intent.putExtra(EXTRA_TASK_LIST, taskList);
        sendBroadcast(intent);
    }

    /**
     * 发送移除广播
     *
     * @param task       移除的对象
     * @param moveResult 是否移除成功
     */
    @MainThread
    public void broadRemoveResult(Task task, boolean moveResult) {
        ALog.i(TAG, "Cancel task " + task + " , moveResult -> " + moveResult);

        Intent intent = new Intent(BROAD_ACTION_REMOVE_RESULT);
        intent.putExtra(EXTRA_TASK, task);
        intent.putExtra(EXTRA_TASK_REMOVE_RESULT, moveResult);
        sendBroadcast(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (DEBUG) ALog.i(TAG, "onDestroy");
        isDestroyed = true;
        mServiceInitialized = false;
        if (mAutoProgressRunnable != null) {
            UI_HANDLER.removeCallbacks(mAutoProgressRunnable);
            mAutoProgressRunnable = null;
        }

        //唤醒扫描器
        if (mExecutorsScanner != null) {
            try {
                mExecutorsScanner.interrupt();
            } catch (Exception ignore) {
            }
            synchronized (mExecutorsScanner) {
                mExecutorsScanner.notifyAll();
            }
        }

        if (mSerialMonitor != null) {
            try {
                mSerialMonitor.interrupt();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }


        //执行销毁回调给执行者工厂
        callBackOnDestroy();
        broadcastOnServiceDestroyed();
    }

    /**
     * 广播执行结果
     *
     * @param task         执行的任务
     * @param isSuccessful 是否执行成功
     * @param e            如果是失败,可以携带一个异常对象
     */
    public void broadcastResult(ExecWrapper task, boolean isSuccessful, Exception e) {
        Intent intent = new Intent(BROAD_ACTION_TASK_EXECUTED);
        intent.putExtra(EXTRA_TASK_EXECUTED_RESULT, isSuccessful);
        intent.putExtra(EXTRA_TASK, task.task);
        intent.putExtra(EXTRA_PROGRESS, task.progress);
        intent.putExtra(EXTRA_EXCEPTION, e);
        if (!isSuccessful && e != null) intent.putExtra(EXTRA_EXCEPTION, e);
        sendBroadcast(intent);

    }

    /**
     * 弹出任务队列中的任务，尝试执行
     */
    public void poolTaskQueue() {
        synchronized (TASK_QUEUE) {
            if (TASK_QUEUE.size() > 0) {
                Task key = TASK_QUEUE.getKey(0);
                Integer value = TASK_QUEUE.remove(key);
                switch (value) {
                    case TYPE_EXEC:
                        cmdAddTask(key);
                        break;
                    case TYPE_RESUME:
                        cmdResumeTask(key.getWhat());
                        break;
                }
                if (DEBUG)
                    ALog.d(TAG, String.format("任务队列中存在未完成的任务 %s 开始执行未完成的任务,队列等待队列长度为 %d", key, TASK_QUEUE.size()));
            }
        }
    }

    /**
     * 在工作线程中执行指定 的 runnable代码
     *
     * @param runnable 需要执行的代码
     */
    public void executeOnWorkThread(Runnable runnable) {
        try {
            runnable.run();
        } catch (Exception e) {
            if (DEBUG) {
                ALog.w(TAG, e);
            }
        }
    }

    /**
     * 在主线程中执行指定的 runnable代码
     *
     * @param runnable 需要执行的代码
     */
    public void executeOnMainThread(Runnable runnable) {
        UI_HANDLER.post(runnable);
    }

    /**
     * 在主线程中执行指定的 runnable代码
     *
     * @param runnable 需要执行的代码
     * @param delay    延时
     */
    public void executeOnMainThread(Runnable runnable, long delay) {
        UI_HANDLER.postDelayed(runnable, delay);
    }

    /**
     * 任务执行者的状态监听器
     * 这个类的设计是为了减少任务执行的操作
     * 这个类主动的去扫描任务执行者当前的任务执行状态
     * 根据他们当前的状态来调整整个服务的状态
     */
    public static class ExecutorsStateMonitor extends Thread {
        public static final String TAG = "ExecutorsStateMonitor";
        private final JobService mJobService;
        private final long mScanInterval;
        private final long exitServiceDelay;

        public ExecutorsStateMonitor(JobService jobService, long scanInterval, long exitServiceDelay) {
            super("Thread-Executors-State-Monitor");
            setDaemon(true);
            setPriority(MIN_PRIORITY);
            this.mJobService = jobService;
            this.mScanInterval = scanInterval;
            this.exitServiceDelay = exitServiceDelay;
        }

        @Override
        public void run() {
            while (!mJobService.isDestroyed && !isInterrupted()) {
                synchronized (this) {
                    if (executorsIsExecuted()) {
                        if (DEBUG)
                            ALog.i(TAG, String.format("当前所有的任务已经执行完毕 %d 后退出服务", exitServiceDelay));
                        mJobService.executeOnMainThread(mJobService.selfKiller, exitServiceDelay);
                        break;
                    }
                    try {
                        wait(mScanInterval);
                    } catch (InterruptedException ignore) {
                    }
                }
            }
        }

        /**
         * 所有的执行者当前是否执行完了任务
         *
         * @return true 或 false
         */
        public boolean executorsIsExecuted() {
            boolean isExecuted = true;
            synchronized (mJobService.EXEC_TASK) {
                for (ExecWrapper wrapper : mJobService.EXEC_TASK) {
                    if (wrapper.progress != null) {
                        synchronized (wrapper.progress) {
                            if (wrapper.progress.getState() == Progress.State.EXECUTING) {
                                isExecuted = false;
                                break;
                            }
                        }
                    }
                }
            }
            return isExecuted;
        }

    }

    /**
     * 序列化监视器
     */
    public static class SerialMonitor extends Thread {

        private final JobService mJobService;
        private final long mSerializeInterval;

        public SerialMonitor(JobService jobService, int serializeInterval) {
            super("Serial-Monitor");
            this.mJobService = jobService;
            this.mSerializeInterval = serializeInterval;
        }

        @Override
        public void run() {
            while (!mJobService.isDestroyed && !isInterrupted()) {
                try {
                    synchronized (mJobService.EXEC_TASK) {
                        for (ExecWrapper wrapper : mJobService.EXEC_TASK) {
                            try {
                                if (wrapper.factory.getTaskSerializer() != null) {
                                    wrapper.factory.getTaskSerializer().serialize(wrapper.task);
                                }
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }

                    synchronized (this) {
                        wait(mSerializeInterval);
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 任务执行包装器
     * Created by lovely3x on 16-2-4.
     */
    public static class ExecWrapper {

        /**
         * 任务执行工厂对象
         */
        public ExecutorFactory factory;

        /**
         * 任务执行者
         */
        public TaskExecutor executor;

        /**
         * 执行的任务对象
         */
        public Task task;

        /**
         * 任务执行的进度
         */
        public Progress progress;

    }
}
